package controllers

import (
	"context"
	"errors"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"gitverse.ru/synapse/kubelatte/pkg/api/v1alpha1"
	"gitverse.ru/synapse/kubelatte/pkg/operator/controllers/mocks"
	controllerruntime "sigs.k8s.io/controller-runtime"
	"testing"
)

func TestTriggerReconciler_updateStatus(t *testing.T) {
	var wantErr bool
	var want controllerruntime.Result
	var isAudit bool
	t.Run("changing_status", func(t *testing.T) {
		wantErr = false
		isAudit = false
		want = controllerruntime.Result{}

		clientM := mocks.NewClient(t)
		subResourceWriterM := mocks.NewSubResourceWriter(t)

		subResourceWriterM.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(nil)
		clientM.On("Status").Return(subResourceWriterM)

		trigger := v1alpha1.Trigger{
			Status: v1alpha1.TriggerStatus{Conditions: []v1alpha1.Condition{{Type: v1alpha1.LastHandledHash}}},
			Spec:   v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-config"}}},
		}

		r := &TriggerReconciler{
			Client:            clientM,
			deletedTriggerObj: v1alpha1.Trigger{Spec: v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-other-config"}}}},
		}
		got, err := r.updateStatus(context.Background(), trigger, isAudit)
		if wantErr != (err != nil) {
			t.Fatalf("error expected to be %v", wantErr)
			return
		}
		assert.Equalf(t, want, got, "updateStatus(%v, %v, %v)", context.Background(), trigger, isAudit)
	})

	t.Run("changing_status", func(t *testing.T) {
		wantErr = false
		isAudit = true
		want = controllerruntime.Result{}

		clientM := mocks.NewClient(t)
		subResourceWriterM := mocks.NewSubResourceWriter(t)

		subResourceWriterM.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(nil)
		clientM.On("Status").Return(subResourceWriterM)

		trigger := v1alpha1.Trigger{
			Status: v1alpha1.TriggerStatus{Conditions: []v1alpha1.Condition{{Type: v1alpha1.LastHandledHash}}},
			Spec:   v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-config"}}},
		}

		r := &TriggerReconciler{
			Client:            clientM,
			deletedTriggerObj: v1alpha1.Trigger{Spec: v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-other-config"}}}},
		}
		got, err := r.updateStatus(context.Background(), trigger, isAudit)
		if wantErr != (err != nil) {
			t.Fatalf("error expected to be %v", wantErr)
			return
		}
		assert.Equalf(t, want, got, "updateStatus(%v, %v, %v)", context.Background(), trigger, isAudit)
	})

	t.Run("changing_status_CheckHashInStatus_false", func(t *testing.T) {
		wantErr = false
		isAudit = false
		want = controllerruntime.Result{}

		clientM := mocks.NewClient(t)
		subResourceWriterM := mocks.NewSubResourceWriter(t)

		subResourceWriterM.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(nil)
		clientM.On("Status").Return(subResourceWriterM)

		trigger := v1alpha1.Trigger{
			Status: v1alpha1.TriggerStatus{Conditions: []v1alpha1.Condition{{Type: "status"}}},
			Spec:   v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-config"}}},
		}

		r := &TriggerReconciler{
			Client:            clientM,
			deletedTriggerObj: v1alpha1.Trigger{Spec: v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-other-config"}}}},
		}
		got, err := r.updateStatus(context.Background(), trigger, isAudit)
		if wantErr != (err != nil) {
			t.Fatalf("error expected to be %v", wantErr)
			return
		}
		assert.Equalf(t, want, got, "updateStatus(%v, %v, %v)", context.Background(), trigger, isAudit)
	})

	t.Run("changing_status_error", func(t *testing.T) {
		wantErr = true
		isAudit = false
		want = controllerruntime.Result{}

		clientM := mocks.NewClient(t)
		subResourceWriterM := mocks.NewSubResourceWriter(t)

		subResourceWriterM.On("Update", mock.Anything, mock.Anything, mock.Anything).Return(errors.New(""))
		clientM.On("Status").Return(subResourceWriterM)

		trigger := v1alpha1.Trigger{
			Status: v1alpha1.TriggerStatus{Conditions: []v1alpha1.Condition{{Type: v1alpha1.LastHandledHash}}},
			Spec:   v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-config"}}},
		}

		r := &TriggerReconciler{
			Client:            clientM,
			deletedTriggerObj: v1alpha1.Trigger{Spec: v1alpha1.TriggerSpec{MutationConfigs: []v1alpha1.MutationConfig{{Name: "some-other-config"}}}},
		}
		got, err := r.updateStatus(context.Background(), trigger, isAudit)
		if wantErr != (err != nil) {
			t.Fatalf("error expected to be %v", wantErr)
			return
		}
		assert.Equalf(t, want, got, "updateStatus(%v, %v, %v)", context.Background(), trigger, isAudit)
	})

}
